﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace UI
{
    public static class UISystem
    {
        private static FormNameHandler _formNameHandler;

        private static List<IUIAssetLoader> _assetLoaders = new List<IUIAssetLoader>();

        private static UISettingsInfo _settings;

        internal static T LoadAsset<T>(string path) where T : UnityEngine.Object
        {
            T asset = null;
            for (var i = 0; i < _assetLoaders.Count; ++i)
            {
                if (_assetLoaders[i].LoadAsset(path, out asset))
                {
                    return asset;
                }
            }
            return Resources.Load<T>(path);
        }

        public static void AddUIHandler(IUIElementCloseHandler handler)
        {
            UIElementHandlers.AddHandler(handler);
        }

        public static void AddUIHandler(IUIElementOpenHandler  handler)
        {
            UIElementHandlers.AddHandler(handler);
        }

        public static void AddUIHandler(IUIElementFreezHandler handler)
        {
            UIElementHandlers.AddHandler(handler);
        }

        internal static void AddUIHandler(IUIFormHideHandler handler)
        {
            UIFormHandlers.AddHandler(handler);
        }

        internal static void AddUIHandler(IUIFormShowHandler handler)
        {
            UIFormHandlers.AddHandler(handler);
        }

        internal static void AddUIHandler(IUIFormFreezHandler handler)
        {
            UIFormHandlers.AddHandler(handler);
        }

        internal static void AddUIHandler(IUIFormCloseHandler handler)
        {
            UIFormHandlers.AddHandler(handler);
        }

        public static void AddAssetLoader(IUIAssetLoader loader)
        {
            _assetLoaders.Insert(0, loader);
        }

        /// <summary>
        /// UI相机
        /// </summary>
        public static Camera UICamera { get; private set; }

        /// <summary>
        /// UI主画布
        /// </summary>
        public static Canvas MainCanvas { get; private set; }

        /// <summary>
        /// UI事件系统
        /// </summary>
        public static EventSystem UIEventSystem
        {
            get; private set;
        }

        public static UISettingsInfo Settings
        {
            get
            {
                if (_settings == null)
                {
                    _settings = LoadAsset<UISettingsInfo>("[UISystemSettings]");
                }
                return _settings;
            }
        }

        private static void InitUICamera()
        {
            UICamera = new GameObject("[UISystem]").AddComponent<Camera>();
            UnityEngine.Object.DontDestroyOnLoad(UICamera.gameObject);
            UICamera.gameObject.layer = LayerMask.NameToLayer("UI");
            UICamera.orthographicSize = Settings.PixelSize.y * 0.005f;
            UICamera.orthographic = true;
            UICamera.depth = 100;
            UICamera.nearClipPlane = 0;
            UICamera.farClipPlane = 1;
            UICamera.clearFlags = CameraClearFlags.Nothing;
            UICamera.cullingMask = 1 << LayerMask.NameToLayer("UI");
        }

        private static void InitUIEventSystem()
        {
            UIEventSystem = new GameObject("[UIEventSystem]").AddComponent<EventSystem>();
            UIEventSystem.gameObject.layer = LayerMask.NameToLayer("UI");
            UIEventSystem.transform.SetParent(UICamera.transform, false);
            UIEventSystem.gameObject.AddComponent<StandaloneInputModule>();
        }

        private static void InitMainCanvas()
        {
            MainCanvas = new GameObject("[MainCanvas]").AddComponent<Canvas>();
            MainCanvas.gameObject.layer = LayerMask.NameToLayer("UI");
            MainCanvas.transform.SetParent(UICamera.transform, false);
            MainCanvas.renderMode = RenderMode.ScreenSpaceCamera;
            MainCanvas.worldCamera = UICamera;
            MainCanvas.planeDistance = 0.5f;
            var canvasScaler = MainCanvas.gameObject.AddComponent<CanvasScaler>();
            canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
            canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;
            canvasScaler.referenceResolution = new Vector2(Settings.PixelSize.x, Settings.PixelSize.y);
            var graphicRaycaster = MainCanvas.gameObject.AddComponent<GraphicRaycaster>();
            graphicRaycaster.blockingObjects = GraphicRaycaster.BlockingObjects.None;
            graphicRaycaster.ignoreReversedGraphics = true;
        }

        private static void InitUILayers()
        {
            var layerNames = Settings.UILayerNames;
            for (var i = 0; i < layerNames.Length; ++i)
            {
                var go = new GameObject(layerNames[i]);
                var rect = go.AddComponent<RectTransform>();
                rect.SetParent(MainCanvas.transform,false);
                rect.anchorMin = Vector2.zero;
                rect.anchorMax = Vector2.one;
                rect.sizeDelta = Vector2.zero;
                rect.anchoredPosition = Vector2.zero;
                var container = go.AddComponent<UIContainer>();
                UIRootContainer.AddContainer(container);
                container.Open();
            }
        }

        public static void Init(FormNameHandler formNameHandler = null)
        {
            _formNameHandler = formNameHandler;
            InitUICamera();
            InitUIEventSystem();
            InitMainCanvas();
            InitUILayers();
        }


        public static UIForm Open(string uiName)
        {
            var form = GetForm(uiName);
            Open(form);
            return form;
        }

        public static UIForm Close(string uiName)
        {
            var form = Find(uiName);
            Close(form);
            return form;
        }

        public static UIForm Freez(string uiName)
        {
            var form = Find(uiName);
            Freez(form);
            return form;
        }


        public static UIForm Find(string uiName)
        {
            if (_formNameHandler != null)
            {
                uiName = _formNameHandler(uiName);
            }
            return UIRootContainer.FindForm(uiName) as UIForm;
        }

        private static UIForm GetForm(string uiName)
        {
            UIForm form = Find(uiName);
            if (form == null)
            {
                if (_formNameHandler != null)
                {
                    uiName = _formNameHandler(uiName);
                }
                form = UIFormLoader.LoadForm(uiName);
                UIRootContainer.AddForm(form);
            }
            return form;
        }

        internal static void Open(UIForm form)
        {
            if (form == null) return;
            UIFormHandlers.Open(form);
        }

        internal static void Close(UIForm form)
        {
            if (form == null) return;
            UIFormHandlers.Close(form);
        }

        internal static void Freez(UIForm form)
        {
            if (form == null) return;
            UIFormHandlers.Freez(form);
        }
    }


}
